package cc.siyecao.fastdfs.command.storage;

import cc.siyecao.fastdfs.enums.MetadataFlag;
import cc.siyecao.fastdfs.model.Metadata;
import cc.siyecao.fastdfs.model.RecvPackageInfo;
import cc.siyecao.fastdfs.protocol.ProtocolConstants;
import cc.siyecao.fastdfs.util.BytesUtil;
import cc.siyecao.fastdfs.util.ProtocolUtil;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Set;

/**
 * 设置文件标签
 *
 * @author lyt
 */
public class SetMetadataCommand extends FdfsStorageCommand<Integer> {

    /**
     * 设置文件标签(元数据)
     */
    public SetMetadataCommand(String groupName, String remoteFileName, Set<Metadata> metaSet, MetadataFlag metadataFlag) {
        this.groupName = groupName;
        this.fileName = remoteFileName;
        this.metaSet = metaSet;
        this.opFlag = metadataFlag.getValue();
    }

    @Override
    protected void send(OutputStream out, Charset charset) throws Exception {
        byte[] header;
        byte[] groupBytes;
        byte[] fileNameBytes;
        byte[] metaBuff;
        byte[] bs;
        int groupLen;
        byte[] sizeBytes;
        if (metaSet == null) {
            metaBuff = new byte[0];
        } else {
            metaBuff = ProtocolUtil.packMetadata( metaSet ).getBytes( charset );
        }
        fileNameBytes = fileName.getBytes( charset );
        sizeBytes = new byte[2 * ProtocolConstants.FDFS_PROTO_PKG_LEN_SIZE];
        Arrays.fill( sizeBytes, (byte) 0 );

        bs = BytesUtil.long2buff( fileNameBytes.length );
        System.arraycopy( bs, 0, sizeBytes, 0, bs.length );
        bs = BytesUtil.long2buff( metaBuff.length );
        System.arraycopy( bs, 0, sizeBytes, ProtocolConstants.FDFS_PROTO_PKG_LEN_SIZE, bs.length );

        groupBytes = new byte[ProtocolConstants.FDFS_GROUP_NAME_MAX_LEN];
        bs = groupName.getBytes( charset );
        Arrays.fill( groupBytes, (byte) 0 );
        if (bs.length <= groupBytes.length) {
            groupLen = bs.length;
        } else {
            groupLen = groupBytes.length;
        }
        System.arraycopy( bs, 0, groupBytes, 0, groupLen );
        header = ProtocolUtil.packHeader( STORAGE_PROTO_CMD_SET_METADATA, 2 * ProtocolConstants.FDFS_PROTO_PKG_LEN_SIZE + 1 + groupBytes.length + fileNameBytes.length + metaBuff.length, (byte) 0 );
        byte[] wholePkg = new byte[header.length + sizeBytes.length + 1 + groupBytes.length + fileNameBytes.length];
        System.arraycopy( header, 0, wholePkg, 0, header.length );
        System.arraycopy( sizeBytes, 0, wholePkg, header.length, sizeBytes.length );
        wholePkg[header.length + sizeBytes.length] = opFlag;
        System.arraycopy( groupBytes, 0, wholePkg, header.length + sizeBytes.length + 1, groupBytes.length );
        System.arraycopy( fileNameBytes, 0, wholePkg, header.length + sizeBytes.length + 1 + groupBytes.length, fileNameBytes.length );
        out.write( wholePkg );
        if (metaBuff.length > 0) {
            out.write( metaBuff );
        }
    }

    @Override
    protected Integer receive(InputStream in, Charset charset) throws Exception {
        RecvPackageInfo pkgInfo = ProtocolUtil.recvPackage( in, STORAGE_PROTO_CMD_RESP, 0 );
        this.errno = pkgInfo.errno;
        if (pkgInfo.errno != 0) {
            return Integer.valueOf( this.errno );
        }
        return 0;
    }
}
